home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / maestro / source / displytl / xvpds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-15  |  19.2 KB  |  652 lines

  1. /*
  2.  * xvpds.c - load routine for astronomical PDS/VICAR format pictures
  3.  * version of 1-5-92
  4.  *
  5.  * Anthony A. Datri
  6.  * Convex Computer Corp
  7.  * 3000 Waterview Parkway
  8.  * Ricardson, TX 75080
  9.  * datri@convex.com
  10.  *
  11.  * 9-2-91    began integration.     Much of this code is lifted from vicar.c,
  12.  *         which I wrote for xloadimage.  This is a little simpler, though.
  13.  * code to identify and read in PDS/VICAR images, as found on the CD-ROMS from
  14.  * NASA, and on ames.arc.nasa.gov.
  15.  *
  16.  * 10-17-91  pdsuncomp is called with system(), which typically feeds the
  17.  *         commandline to sh.  Make sure that your .profile adds wherever
  18.  *         you have pdsuncomp to the PATH, like
  19.  *
  20.  *        PATH=$PATH:/usr/local/bin
  21.  * 11-15-91  substituted vdcomp from Viking CD's for pdsuncomp. I added
  22.  *           recognition of - and shut off various messages
  23.  *
  24.  * 1-5-92    merged into xv rel 2
  25.  *
  26.  * Sources of these CD's:
  27.  *
  28.  *  National Space Science Data Center
  29.  *  Goddard Space Flight Center
  30.  *  Code 933.4
  31.  *  Greenbelt, Maryland  
  32.  *  (301) 286-6695
  33.  *   or call
  34.  *  (301) 286-9000 (300,1200,2400 bps)
  35.  *   or telnet
  36.  *  nssdca.gsfc.nasa.gov (128.183.10.4) and log in as 'NODIS' (no password).
  37.  *
  38.  *  Randy Davis
  39.  *  LASP
  40.  *  University of Colorado
  41.  *  Boulder CO 80309-0392
  42.  *  (303) 492-6867
  43.  * These CD's are reasonably priced.  Encourage the continue production
  44.  * of them by buying a set.
  45.  * There are three types of files that we deal with here.  I'll call them
  46.  * PDS-labeled, PDS-labeled Huffman-encoded, and VICAR.  Each consists of data
  47.  * prefixed with a set of ASCII headers.  PDS-labeled and VICAR files are raw
  48.  * grayscale data, the dimensions of which can be found from the headers.
  49.  * PDS-labeled, Huffman-encoded files have the image information adaptively
  50.  * Huffman-encoded, and the encoding histogram follows the ASCII headers.
  51.  * To decode these, we use an extended version of "cdcomp.c" from the
  52.  * NASA Vger CD-ROMS.  For this to work, you need to have pdscomp compiled
  53.  * and in your path.  pdscomp.c should be included with this distribution.
  54.  * I've heard that newer discs have FITS images on them.  If they do, support
  55.  * for them will be added when I get one.  Until then, you can use fitstopgm.
  56.  *
  57.  * LoadPDS(fname, numcols)  -  coerces a PDS/VICAR image
  58.  * WriteVICAR(fp, pic, w, h, r,g,b, numcols, style)
  59.  */
  60.  
  61. /*
  62.  * Copyright 1989, 1990 by Anthony A. Datri
  63.  *
  64.  * Permission to use, copy, and distribute for non-commercial purposes,
  65.  * is hereby granted without fee, providing that the above copyright
  66.  * notice appear in all copies and that both the copyright notice and this
  67.  * permission notice appear in supporting documentation.
  68.  *
  69.  * This software is provided "as is" without any express or implied warranty.
  70.  */
  71.  
  72.  
  73. #include "xvimage.h"
  74.  
  75.  
  76. #define PDSFIXED        (1)
  77. #define PDSVARIABLE     (2)
  78. #define PDSTRASH        (-1)
  79. #define VICAR           (3)
  80. #define VIKINGFIXED     (4) /* Viking discs have a unique variant */
  81. #define VIKINGVARIABLE  (5)
  82.  
  83.  
  84. #ifndef TRUE
  85. #define TRUE (1)
  86. #define FALSE (0)
  87. #endif
  88.  
  89. #define MAX_SIZE    20480   /* a guess -- even magellan images aren't
  90.                     bigger than 2k x 2k */
  91. #define RTBUFFSIZE    62    /* small buffer for magic */
  92. #define FNAMESIZE    1024    /* too hard to generalize really getting it */
  93. #define PDSUNCOMP    "vdcomp" /* filter to un-Huffmanize */
  94.  
  95. /* This is arbitrary.  Everything I've seen so far fits */
  96. #define COMMENTSIZE    50
  97.  
  98.  
  99. static char    scanbuff      [MAX_SIZE], 
  100.                 rtbuff        [RTBUFFSIZE], 
  101.                 infobuff      [COMMENTSIZE],
  102.         spacecraft    [COMMENTSIZE],
  103.         target        [COMMENTSIZE],
  104.         filtname      [COMMENTSIZE],
  105.         mphase        [COMMENTSIZE],
  106.         iname         [COMMENTSIZE],
  107.         itime         [COMMENTSIZE],
  108.         pdsuncompfname[FNAMESIZE];
  109. byte *image;
  110.  
  111.  
  112. /* 
  113.  * pds_strstr.c --
  114.  *
  115.  *    Source code for the "strstr" library routine.
  116.  *
  117.  * Copyright 1988 Regents of the University of California
  118.  * Permission to use, copy, modify, and distribute this
  119.  * software and its documentation for any purpose and without
  120.  * fee is hereby granted, provided that the above copyright
  121.  * notice appear in all copies.  The University of California
  122.  * makes no representations about the suitability of this
  123.  * software for any purpose.  It is provided "as is" without
  124.  * express or implied warranty.
  125.  */
  126.  
  127. /*
  128.  *----------------------------------------------------------------------
  129.  *
  130.  * pds_strstr --
  131.  *
  132.  *    Locate the first instance of a substring in a string.
  133.  *
  134.  * Results:
  135.  *    If string contains substring, the return value is the
  136.  *    location of the first matching instance of substring
  137.  *    in string.  If string doesn't contain substring, the
  138.  *    return value is 0.  Matching is done on an exact
  139.  *    character-for-character basis with no wildcards or special
  140.  *    characters.
  141.  *
  142.  * Side effects:
  143.  *    None.
  144.  *
  145.  *----------------------------------------------------------------------
  146.  */
  147.  
  148. char *pds_strstr(string, substring)
  149.      char *string;    /* String to search. */
  150.      char *substring;        /* Substring to try to find in string. */
  151. {
  152.   register char *a, *b;
  153.  
  154.   /* First scan quickly through the two strings looking for a
  155.    * single-character match.  When it's found, then compare the
  156.    * rest of the substring.
  157.    */
  158.  
  159.   b = substring;
  160.   if (*b == 0) return string;
  161.  
  162.   for ( ; *string != 0; string += 1) {
  163.     if (*string != *b) continue;
  164.  
  165.     a = string;
  166.     while (1) {
  167.       if (*b == 0) return string;
  168.  
  169.       if (*a++ != *b++) break;
  170.  
  171.     }
  172.     b = substring;
  173.   }
  174.   return (char *) 0;
  175. }
  176.  
  177.  
  178.  
  179.  
  180.  
  181. /* get a NULL-, CR-, or CRLF-terminated record from a PDS file */
  182. /* The method of termination is unpredictable.  A pox on VMS   */
  183.  
  184. int getpdsrec(f,buff)
  185.      FILE *f;
  186.      char *buff;
  187. {
  188.   static char *bp;
  189.   static int count;
  190.  
  191.   count=0;
  192.   bp=buff;
  193.   while (1) {
  194.     (*bp)=fgetc(f);
  195.     switch (*bp) {
  196.  
  197.     case '\r':  *bp='\0';
  198.                 switch ((*(bp+1))=fgetc(f)) {
  199.           case EOF:
  200.           case '\n':  break;
  201.                   default:    ungetc(*(bp+1),f);
  202.           }
  203.                 return(count);
  204.  
  205.     case EOF:    *bp='\0';  return(count);            
  206.     
  207.     case '\0':  return(count);
  208.     
  209.     default:    count++;  bp++;
  210.     }
  211.   }
  212. }
  213.  
  214.  
  215. /* A VICAR image seems to begin with a one-line header describing all sorts
  216.  * of things, almost all of which don't mean much to Joe User, who just
  217.  * wants to see what Venus looks like.  The first thing in this label is a
  218.  * string defining the size of the label, like "LBLSIZE=2048".  Then there's
  219.  * other crud of variable usefulness.  Important to us are the NL and NS
  220.  * fields, which seem to tell us the number of columns and rows, respectively.
  221.  * Among these other fields seem to be the local map coordinates of the region.
  222.  * These files are easy -- you can even convert one to usefulness by grabbing
  223.  * the dimensions and lblsize and feeding to rawtopgm.  Example, if lblsize,
  224.  * nl, and ns are 2048, 1536, and 2048, respectively, use "rawtopgm -headerskip
  225.  * 2048 2048 1536 <foo.img >foo.pgm.  All of the samples I've seen are 8 bits
  226.  * deep, so we assume that.  Yeah, yeah, that's nasty and evil, and I'm
  227.  * terribly ashamed of it, but I'm not going to bother with bit fiddling
  228.  * until I see an image that requires it
  229.  *
  230.  * These images are typically fairly big, so it makes sense to verify the
  231.  * format before we try to read it all in.
  232.  *
  233.  * PDS images are prefixed like this:
  234.  *
  235.  *  od -a c2061139.imq | head -a
  236.  *  0000000    - nul   N   J   P   L   1   I   0   0   P   D   S   1   0   0
  237.  *
  238.  * so we'll read off the first two chars, which seem to be a length field
  239.  * of some kind, then look for NJPL..  But NOOOOOO, images on the Sampler
  240.  * disc just HAVE to leave off the first two bytes.  Bloody HELL!  This
  241.  * is the distinction between the fixed and variable-record files.
  242.  */
  243.             
  244. /*******************************************/
  245. int LoadPDS(fname,nc)
  246.      char *fname;
  247.      int   nc;
  248. {
  249.  
  250.   int tempnum;
  251.   FILE    *zf;
  252.   static int isfixed,teco,i,j,itype,lastwasinote,
  253.              recsize,hrecsize,irecsize,isimage,labelrecs,labelsofar,
  254.              x,y,lpsize,lssize,samplesize,returnp,labelsize,yy;
  255.   char    *tmp;
  256.   char  *ftypstr;
  257.   unsigned long filesize;
  258.  
  259.   isfixed = TRUE;
  260.   returnp = isimage = FALSE;
  261.   itype   = PDSTRASH;
  262.  
  263.   teco = i = j = recsize = hrecsize = irecsize = labelrecs = x = y = 0;
  264.   lpsize = lssize = samplesize = labelsize = labelsofar = 0;
  265.  
  266.   (*pdsuncompfname) = (*iname) = (*target) = (*filtname) = '\0';
  267.   (*itime) = (*spacecraft) = (*scanbuff) = (*mphase) = (*rtbuff) = '\0';
  268.  
  269.   /* there may be some wisdom in statically mallocing space for an 800x800
  270.      image, since that's what the Voyager cd's have, or even a 2kx2k, since
  271.      some of the Magellan images from ames are that size */
  272.  
  273.  
  274.   zf=fopen(fname,"r");
  275.   if (!zf) {
  276.     printf("LoadPDS: can't open %s\n",fname);
  277.     return(1);
  278.   }
  279.  
  280.   /* figure out the file size (for Informational Purposes Only) */
  281.   fseek(zf, 0L, 2);
  282.   filesize = ftell(zf);
  283.   fseek(zf, 0L, 0);
  284.  
  285.  
  286.   /* read the magic.  If it's got two bytes of crud in front of it, it's
  287.      a damned "variable-length-record" file, and we have to jump through
  288.      bloody VAX hoops, and feed it through pdsuncomp to get useful bits */
  289.  
  290.   if ((teco=fread(rtbuff,13,1,zf)) != 1) {
  291.     printf("LoadPDS: couldn't read magic #: %d,%s\n",teco,fname);
  292.     fclose(zf);
  293.     return(1);
  294.   }
  295.  
  296.   /* this makes sscanf so much happier */
  297.   rtbuff[RTBUFFSIZE-1] = 0;
  298.  
  299.   if (strncmp(rtbuff, "NJPL1I00PDS",11) == 0) {
  300.     itype=PDSFIXED;
  301.   } else if (strncmp(rtbuff+2,"NJPL1I00PDS",11) == 0) {
  302.     itype=PDSVARIABLE;
  303.   } else if (strncmp(rtbuff,"CCSD3Z",6) == 0) {
  304.     itype=VIKINGFIXED; /* unique variant of PDS on Viking discs (browse) */
  305.   } else if (strncmp(rtbuff+2,"CCSD3Z",6) == 0) {
  306.     itype=VIKINGVARIABLE;
  307.   } else if (sscanf(rtbuff,"LBLSIZE = %d%n",&labelsize,&labelsofar) == 1) {
  308.     itype=VICAR;
  309.   } else {
  310.     printf("LoadPDS: can't handle this file, for some reason\n");
  311.     fclose(zf);
  312.     return(1);
  313.   }
  314.  
  315.   switch (itype) {
  316.   case PDSFIXED:
  317.   case VICAR:
  318.   case VIKINGFIXED:     isfixed=TRUE;
  319.                         sprintf(formatStr, "PDS/VICAR, 8 bits per pixel. (%ld bytes)",
  320.                 filesize);
  321.                         break;
  322.   case PDSVARIABLE:
  323.   case VIKINGVARIABLE:  isfixed=FALSE;
  324.                         sprintf(formatStr, "Huffman-encoded PDS, 8 bits per pixel. (%ld bytes)",
  325.                 filesize);
  326.   }
  327.  
  328.   if ((itype == PDSFIXED) || (itype == PDSVARIABLE) ||
  329.       (itype == VIKINGFIXED) || (itype == VIKINGVARIABLE)) {
  330.  
  331.     if (isfixed == FALSE) {
  332.       teco = ((*rtbuff) + ((*(rtbuff+1)) << 8));
  333.       fread(rtbuff,(teco % 2 ? teco + 1 : teco ) - 11,1,zf);
  334.     }
  335.  
  336.     /* we know that we've got a PDS file of some sort.    We have to
  337.        search through the labels looking for things because usage doesn't seem
  338.        to be consistent, or even predictable.  When I added this format to
  339.        xloadimage, I had the code spew out various peices of information, like
  340.        the name of the target, filter used, etc.  Xv, however, doesn't really
  341.        provide a mechanism for this kind of thing, and I can't really stick it
  342.        into the info box without overhauling it.  Maybe later I'll add a
  343.        -verbose switch which this module will interpret as license to scribble
  344.        on stdout or stderr */
  345.  
  346.     for (;;) {
  347.       if (isfixed) {
  348.     if (getpdsrec(zf,scanbuff) == 0) {
  349.       printf("corrupt or incomplete PDS labels (low fread)\n");
  350.       break;
  351.     }
  352.       } else {
  353.     /* AAAARGGGGH!  We've got a bloody variable-length file where
  354.      * the headers are preceded by a byte count, as a VAX 16-bit
  355.      * integer of all things.  VMS:  Just Say NFW.
  356.      * "A compressed image file is composed of variable-length records
  357.      * defined according to the ISO standard.  Each variable length
  358.      * record starts with a record length indicator, stored as a 16-bit
  359.      * integer, followed by the number of bytes indicated in the record
  360.      * length indicator. If the length indicator is odd, then a pad byte
  361.      * is appended to the end of the record so that all records contain
  362.      * an even number of bytes."*/
  363.                                                                         
  364.     i=getc(zf);
  365.     j=getc(zf);
  366.     if (j == EOF) {
  367.       printf("LoadPDS: j is EOF\n");
  368.       fclose(zf);
  369.       return(1);
  370.     }
  371.     
  372.     teco = i + (j << 8);
  373.     if (teco % 2) teco++;
  374.  
  375.     if (fread(scanbuff,teco,1,zf) != 1) {
  376.       printf("LoadPDS: bad fread reading labels\n");
  377.       fclose(zf);
  378.       return(1);
  379.     }
  380.     
  381.     scanbuff[teco]='\0';
  382.       }
  383.  
  384.       /* otay, we've managed to wrestle a header of some sort from the
  385.      file -- now we grep through until we hit the END, at which point
  386.      we break out of the loop and see what we've got.  In the future,
  387.      we'll check for informational headers and write them out if the
  388.      fool user wants them.  There seems to be disagreement about what
  389.      the headers are called, since we might find, for example, either
  390.      TARGET_BODY or TARGET_NAME.    Bloody 'ell. */
  391.  
  392.       if (strcmp(scanbuff,"END") == 0) {
  393.     break;
  394.       } else if (sscanf(scanbuff,"RECORD_TYPE = %s",rtbuff) == 1) {
  395.     if (strncmp(rtbuff,"VARIABLE_LENGTH",15) == 0) {
  396.       /*        itype=PDSVARIABLE; */
  397.     } else if (strncmp(rtbuff,"FIXED_LENGTH",12) == 0) {
  398.       /*        itype=PDSFIXED;*/
  399.     } else {
  400.       rtbuff[RTBUFFSIZE-1]='\0'; /* juuuust in case */
  401.       printf("LoadPDS: unsupported record type \"%s\"\n",rtbuff);
  402.       fclose(zf);
  403.       return(1);
  404.     }
  405.       } else if (sscanf(scanbuff,"RECORD_BYTES = %d",&recsize) == 1) {
  406.     /* these default to RECORD_BYTES unless explicitly set */
  407.     if (hrecsize == 0) hrecsize=recsize;
  408.         if (irecsize == 0) irecsize=recsize;
  409.     continue;
  410.       } else if (sscanf(scanbuff,"FILE_TYPE = %s", rtbuff) != NULL) {
  411.     if (strncmp(rtbuff,"IMAGE",5) == 0) {
  412.       isimage=TRUE;
  413.       continue;
  414.     } else {
  415.       isimage=FALSE;
  416.       break;
  417.     }
  418.       } else if ((sscanf(scanbuff," HEADER_RECORDS = %d",&labelrecs) == 1) ||
  419.          (sscanf(scanbuff," LABEL_RECORDS = %d", &labelrecs) == 1)) {
  420.     continue;
  421.       } else if (sscanf(scanbuff," IMAGE_LINES = %d",&y) == 1) {
  422.     isimage=TRUE; continue;
  423.       } else if (sscanf(scanbuff," LINE_SAMPLES = %d",&x) == 1) {
  424.     continue;
  425.       } else if (sscanf(scanbuff," LINES = %d",&y) == 1) {
  426.     isimage=TRUE; continue;
  427.       } else if (sscanf(scanbuff," HEADER_RECORD_BYTES = %d",&hrecsize)==1) {
  428.     continue;
  429.       } else if (sscanf(scanbuff," IMAGE_RECORD_BYTES = %d",&irecsize)==1) {
  430.     continue;
  431.       } else if (sscanf(scanbuff," LINE_PREFIX_BYTES = %d",&lpsize)==1) {
  432.     continue;
  433.       } else if (sscanf(scanbuff," LINE_SUFFIX_BYTES = %d",&lssize)==1) {
  434.     continue;
  435.       } else if (sscanf(scanbuff," SAMPLE_BITS = %d", &samplesize) == 1) {
  436.     continue;
  437.       } else if (sscanf(scanbuff," SPACECRAFT_NAME = %s", spacecraft) == 1) {
  438.     continue;
  439.  
  440.       } else if (sscanf(scanbuff," TARGET_NAME = %s", target) == 1) {
  441.     continue;
  442.       } else if (sscanf(scanbuff," TARGET_BODY = %s", target) == 1) {
  443.     continue;
  444.  
  445.       } else if (sscanf(scanbuff," SPACECRAFT_EVENT_TIME = %s", itime) == 1) {
  446.     continue;
  447.       } else if (sscanf(scanbuff," IMAGE_TIME = %s", itime) == 1) {
  448.     continue;
  449.       } else if (sscanf(scanbuff," FILTER_NAME = %s", filtname) == 1) {
  450.     continue;
  451.       } else if (sscanf(scanbuff," INSTRUMENT_FILTER_NAME = %s", filtname) 
  452.          == 1) {
  453.     continue;
  454.       }
  455.     }
  456.  
  457.     if ((isimage == TRUE) && (labelsize=(labelrecs * hrecsize))) {
  458.       if (samplesize!= 8) {
  459.     printf("This image is not an 8-bit PDS file.  Sorry.\n");
  460.     fclose(zf);
  461.     return(1);
  462.       }
  463.     } else {
  464.       printf("This looks like a PDS/VICAR image, but not enough.\n");
  465.       fclose(zf);
  466.       return(1);
  467.     }
  468.  
  469.     /* Some day this should be generalized to read <>8-bit files.  If I 
  470.        ever find one that's interesting, I'll do the work. */
  471.  
  472.   } else if (itype == VICAR) {
  473.     /* we've got a VICAR file.  Let's find out how big the puppy is */
  474.  
  475.     if (fread(scanbuff,labelsize-labelsofar,1,zf) == 1) {
  476.       if ((tmp = (char *) pds_strstr(scanbuff,"NL=")) == NULL) {
  477.     printf("LoadPDS: bad NL in VICAR\n");
  478.     returnp=TRUE;
  479.       }
  480.       
  481.       if (sscanf(tmp,"NL = %d",&y) != 1) {
  482.     printf("LoadPDS: bad scan NL in VICAR\n");
  483.     returnp=TRUE;
  484.       }
  485.  
  486.       if ((tmp = (char *) pds_strstr(scanbuff, "NS=")) == NULL) {
  487.     printf("LoadPDS: bad NS in VICAR\n");
  488.     returnp=TRUE;
  489.       }
  490.  
  491.       if (sscanf(tmp, "NS = %d",&x) != 1) {
  492.     printf("LoadPDS: bad scan NS in VICAR\n");
  493.     returnp=TRUE;
  494.       }
  495.     }
  496.  
  497.   } else {
  498.     printf("LoadPDS: Unable to parse data.\n");
  499.     returnp=TRUE;
  500.   }
  501.  
  502.   if (returnp) {
  503.     fclose(zf);
  504.     return(1);
  505.   }
  506.  
  507.   /* PDS files tend to have lots of information like this in them.  The
  508.    * following are a few of the more interesting headers.  We'd do more, but
  509.    * there's only so much space in the info box */
  510.  
  511.   *infobuff='\0';
  512.   if (*spacecraft) {
  513.     strcat(infobuff,spacecraft);
  514.   }
  515.  
  516.   if (*target) {
  517.     strcat(infobuff,", ");
  518.     strcat(infobuff,target);
  519.   }
  520.  
  521.   if (*filtname) {
  522.     strcat(infobuff,", ");
  523.     strcat(infobuff,filtname);
  524.   }
  525.  
  526.   if (*itime) {
  527.     strcat(infobuff,", ");
  528.     strcat(infobuff,itime);
  529.   }
  530.  
  531.   printf(infobuff);
  532.  
  533.   strcpy(pdsuncompfname,fname);
  534.   ftypstr = "";
  535.  
  536.   switch (itype) {
  537.   case VICAR:
  538.     sprintf(formatStr, "VICAR, 8 bits per pixel. (%ld bytes)", filesize);
  539.     ftypstr = "VICAR";
  540.     rewind(zf);
  541.     break;
  542.  
  543.   case PDSFIXED:
  544.   case VIKINGFIXED:
  545.     sprintf(formatStr, "PDS, 8 bits per pixel. (%ld bytes)", filesize);
  546.     ftypstr = "PDS";
  547.     rewind(zf);
  548.     break;
  549.  
  550.   case PDSVARIABLE:
  551.   case VIKINGVARIABLE:
  552.     sprintf(formatStr, "PDS, 8 bits per pixel, Huffman-encoded. (%ld bytes)",
  553.         filesize);
  554.     ftypstr = "PDS (Huffman)";
  555.     fclose(zf);
  556.     strcpy(pdsuncompfname,"/tmp/xvhuffXXXXXX");
  557.     mktemp(pdsuncompfname);
  558.     sprintf(scanbuff,"%s %s - 4 >%s\n",PDSUNCOMP,fname,pdsuncompfname);
  559.     printf("De-Huffmanizing '%s'...\n",fname);
  560.     /* pdsuncomp filters to a raw file */
  561.     if (tempnum=system(scanbuff)) {
  562.       printf("Unable to de-Huffmanize '%s'.\n",fname);
  563.       return(1);
  564.     }
  565.  
  566.     zf=fopen(pdsuncompfname,"r");
  567.     if (!zf) {
  568.       printf("LoadPDS: can't open uncompressed file %s\n",
  569.           pdsuncompfname);
  570.       return(1);
  571.     }
  572.   }
  573.  
  574.   /* skip headers */
  575.  
  576.   if ( isfixed == TRUE ) {
  577.     fread(scanbuff,labelsize,1,zf);
  578.   }
  579.  
  580.   image=(byte *)malloc(x*y);
  581.   if (image == NULL) {
  582.     printf("LoadPDS: couldn't malloc %d\n",x*y);
  583.     fclose(zf);
  584.     if (isfixed == FALSE)
  585.       unlink(pdsuncompfname);
  586.     exit(1);
  587.   }
  588.  
  589.   if ((lssize || lpsize) && ((itype == PDSFIXED) || (itype == VIKINGFIXED)) ) {
  590.     /* ARrrrgh.  Some of these images have crud intermixed with the image, */
  591.     /* preventing us from freading in one fell swoop */
  592.     /* (whatever a fell swoop is */
  593.  
  594.     for (yy=0; yy<y; yy++) {
  595.       if (lpsize && ((teco=(fread(scanbuff,lpsize,1,zf))) != 1)) {
  596.     printf( "LoadPDS: unexpected EOF reading prefix\n");
  597.     fclose(zf);
  598.     return(1);
  599.       }
  600.  
  601.       if ((teco=(fread(image+(yy*x),x,1,zf))) != 1) {
  602.     printf( "LoadPDS: unexpected EOF reading line %d\n",yy);
  603.     fclose(zf);
  604.     return(1);
  605.       }
  606.  
  607.       if (lssize && ((teco=(fread(scanbuff,lssize,1,zf))) != 1)) {
  608.     printf( "LoadPDS: unexpected EOF reading suffix\n");
  609.     fclose(zf);
  610.     return(1);
  611.       }
  612.     }
  613.  
  614.   } else if ((yy=fread(image,x*y,1,zf)) != 1) {
  615.     printf("LoadPDS: error reading image data\n");
  616.     fclose(zf);
  617.     if (itype==PDSVARIABLE || itype==VIKINGVARIABLE)
  618.       unlink(pdsuncompfname);
  619.  
  620.     return(1);
  621.   }
  622.  
  623.   fclose(zf);
  624.   if (isfixed == FALSE)
  625.     unlink(pdsuncompfname);
  626.  
  627.   pic = image;
  628.   pWIDE = x;
  629.   pHIGH = y;
  630.  
  631.   /* these are grayscale, so cobble up a ramped colormap */
  632.   /* Viking images on the CD's seem to be inverted.  Sigh */
  633.  
  634.   switch (itype) {
  635.   case PDSVARIABLE:
  636.   case PDSFIXED:
  637.   case VICAR:
  638.     for (yy=0; yy<=255; yy++) {
  639.       r[yy] = g[yy] = b[yy] = yy;
  640.     }
  641.     break;
  642.  
  643.   case VIKINGFIXED:
  644.   case VIKINGVARIABLE:
  645.     for (yy=0; yy<=255; yy++) {
  646.       r[yy] = g[yy] = b[yy] = (255-yy);
  647.     }
  648.   }
  649.  
  650.   return(0);
  651. }
  652.